/**
 * @Description: app状态管理
 * @Author 卞鹏飞 <228443632@qq.com>
 * @create 02/08/24 3:36 PM
 */

import { defineStore } from 'pinia'
import pkg from '@root/package.json'
import { isFunction, isPlainObject, isString, uuid } from 'sf-utils2'
import useAppStore from '@store/use-app-store'
import profile from '@root/profile'

// types
import type { IAppStateTabItem } from '@root/types/app-store'
import type { TLayoutState, TabItemUnion } from '@root/types/layout-store'

const id = 'layoutStore'
const storageKey = `__persisted__${pkg.name}__${pkg.version}__${id}`

export default defineStore(id, {
  state: (): TLayoutState =>
    <TLayoutState>{
      xhrLoading: false, // 请求接口loading
      loading: false, // loading 全局loading
      pageCache: true, // 是否要开启页面缓存
      isHeaderShow: true, // header头部展示
      isTabShow: true, // tabs展示
      isMenuShow: true, // menus展示
      collapse: false, // 菜单折叠
      tabs: [], // 标签tabs
      reloadRoute: () => {}, // 重新刷新路由
      removeIframeRoute: () => {}, // 移除路由
      /**
       * @deprecated 废弃了
       */
      beforeCloseRoute: {}, // 关闭路由
      beforeCloseRouteV2: {}, // 关闭路由
      menuActive: undefined, // 菜单 当前选中
      tabsActive: undefined // tabs 当前选中的
    },

  getters: {},

  actions: {
    /**
     * 获取当前激活的tab具体信息
     * @param {ITabItem|string} tab
     */
    getActiveTabInfo(tab?: TabItemUnion) {
      let idx = -1
      tab ||= this.tabsActive
      if (isString(tab)) {
        const tempTabs = tab as string
        idx = this.tabs.findIndex((v) => v?.key === tempTabs)
      } else if (isPlainObject(tab)) {
        const tempTabs = tab as IAppStateTabItem
        idx = this.tabs.findIndex((v) => v?.key === tempTabs!.key)
      }
      return {
        idx,
        targetTab: this.tabs[idx]
      }
    },

    /**
     * 关闭其他tab
     * @param {string} tabKey tab唯一标识
     * @return {Promise<void>}
     */
    async closeOthers(tabKey: string) {
      let { idx, targetTab } = this.getActiveTabInfo(tabKey)
      if (~idx) {
        const delTabKeysMap = {} // 可以关闭tab
        let nearestIdx = -1 // 最近的不可直接关闭tab索引

        this.tabs.forEach((item, index) => {
          if (item?.key != targetTab?.key) {
            if (this.isExecBeforeCloseCb(item.key)) {
              if (!~nearestIdx) nearestIdx = index
            } else {
              delTabKeysMap[item.key] = true
            }
          }
        })
        const { targetTab: activeTargetTab } = this.getActiveTabInfo()
        delete delTabKeysMap[activeTargetTab.key]

        this.tabs = this.tabs.filter((v) => !delTabKeysMap[v.key])
      }
    },

    // 关闭左侧
    async closeOthersLeft(tabKey: string) {
      let { idx } = this.getActiveTabInfo(tabKey)
      if (~idx) {
        const delTabKeysMap = {} // 可以关闭tab
        let nearestIdx = -1 // 最近的不可直接关闭tab索引

        for (let i = 0, len = this.tabs.length; i < len; i++) {
          if (i < idx) {
            let item = this.tabs[i]
            if (this.isExecBeforeCloseCb(item.key)) {
              if (!~nearestIdx) nearestIdx = i
            } else {
              delTabKeysMap[item.key] = true
            }
          }
        }
        const { targetTab: activeTargetTab } = this.getActiveTabInfo()
        delete delTabKeysMap[activeTargetTab.key]

        this.tabs = this.tabs.filter((v) => !delTabKeysMap[v.key])
        if (~nearestIdx) {
          const { router } = useAppStore()
          const tempTab = this.tabs[nearestIdx]
          await router.push(tempTab.key)
        }
      }
    },

    // 关闭右侧
    async closeOthersRight(tabKey: string) {
      let { idx } = this.getActiveTabInfo(tabKey)
      if (~idx) {
        const delTabKeysMap = {} // 可以关闭tab
        let nearestIdx = -1 // 最近的不可直接关闭tab索引

        for (let len = this.tabs.length, i = len - 1; i >= 0; i--) {
          if (i > idx) {
            let item = this.tabs[i]
            if (this.isExecBeforeCloseCb(item.key)) {
              if (!~nearestIdx) nearestIdx = i
            } else {
              delTabKeysMap[item.key] = true
            }
          }
        }
        const { targetTab: activeTargetTab } = this.getActiveTabInfo()
        delete delTabKeysMap[activeTargetTab.key]

        this.tabs = this.tabs.filter((v) => !delTabKeysMap[v.key])
        if (~nearestIdx) {
          const { router } = useAppStore()
          const tempTab = this.tabs[nearestIdx]
          await router.push(tempTab.key)
        }
      }
    },

    /**
     * 关闭tab
     * @returns {Promise<void>}
     */
    closeTab(...args: any[]) {
      return this.removeTab.call(this, ...args)
    },

    /**
     * 新增tab
     * @param {Object} tab
     */
    addTab(tab: IAppStateTabItem) {
      tab ||= {}
      const tabObj = {
        ...tab,
        key: tab?.key || uuid(),
        title: tab.title,
        fullPath: tab.fullPath
      }

      // 当前的tab索引
      const { idx: currentIdx } = this.getActiveTabInfo()

      let { idx, targetTab } = this.getActiveTabInfo(tabObj)
      if (!~idx) {
        // 不存在
        // fix 支持修复新打开页最好跟在当前页面之后
        ~currentIdx ? this.tabs.splice(currentIdx + 1, 0, tabObj) : this.tabs.push(tabObj)
      } else {
        tabObj.title = targetTab?.title || tabObj?.title
        this.tabs.splice(idx, 1, Object.assign(targetTab, tabObj))
      }
      this.tabsActive = tabObj?.key
    },

    /**
     * 判断是否可以运行beforeClose
     * @param tabKey
     * @return {boolean}
     */
    isExecBeforeCloseCb(tabKey: string): boolean {
      return !!this.beforeCloseRoute[tabKey]?.length
    },

    /**
     * 移除tab
     * @param {Object|String} tab
     * @param options {{autoJump: boolean}} 是否自动跳转
     */
    async removeTab(tab: TabItemUnion, options = { autoJump: true }) {
      let { idx, targetTab } = this.getActiveTabInfo(tab)
      if (~idx) {
        this.tabs.splice(idx, 1)
        if (options.autoJump && targetTab?.key === this.tabsActive) {
          this.tabsActive = this.tabs[idx - 1]?.key || this.tabs[0]?.key
        }
        // TODO 卞
        // const appStore = useAppStore()
        // appStore.bus.emit(OPERATE_REMOVE_TAB, targetTab.key)
      }
    },

    /**
     * 刷新
     */
    async refresh(tabKey: string) {
      const getAppName = (url) => url.split('/')[0] // 获取应用名称
      tabKey ||= this.tabsActive
      let { idx } = this.getActiveTabInfo(tabKey)
      if (~idx) {
        const { router } = useAppStore()
        const appName = getAppName(router.currentRoute.path)
        const microAppInfo = profile.apps.find((v) => (v as any)!.name == appName)
        if (microAppInfo) {
          // 如果是 microApp 则刷新
          this.reloadRoute((tabKey as IAppStateTabItem).key || tabKey)
        } else {
          // 普通路由 刷新
          this.reloadRoute(tabKey)
        }
      }
    },

    /**
     * 更新tab
     * @param {Object|String} tab
     */
    updateTab(tab: TabItemUnion) {
      if (isPlainObject(tab)) {
        const tabAlias = tab as IAppStateTabItem
        if (!tabAlias?.key) {
          const { router } = useAppStore()
          tabAlias.key = router.currentRoute.fullPath
        }
      }
      let { idx, targetTab } = this.getActiveTabInfo(tab)
      if (~idx) {
        this.tabs.splice(idx, 1, Object.assign(targetTab, tab))
      }
    },

    /**
     * 加载
     * @param {Function|any} cb 回调函数
     * @return {Promise<void>}
     */
    async load(cb) {
      try {
        this.loading = true
        return await (isFunction(cb) ? cb() : cb)
      } finally {
        this.loading = false
      }
    }
  },

  persist: {
    key: storageKey,
    storage: sessionStorage,
    paths: ['tabs', 'collapse'] // undefined 缓存全部
  }
})
